namespace PickGold.Charting
{
    using System;

    internal class ChartHelper
    {
        internal const int MaxNumOfGridlines = 0x2710;

        private ChartHelper()
        {
        }

        internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type)
        {
            return AlignIntervalStart(start, intervalSize, type, null);
        }

        internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series)
        {
            return AlignIntervalStart(start, intervalSize, type, series, true);
        }

        internal static double AlignIntervalStart(double start, double intervalSize, DateTimeIntervalType type, Series series, bool majorInterval)
        {
            if ((series != null) && series.IsXValueIndexed)
            {
                if ((type != DateTimeIntervalType.Auto) && (type != DateTimeIntervalType.Number))
                {
                    return (double) -(series.Points.Count + 1);
                }
                if (majorInterval)
                {
                    return 1.0;
                }
                return 0.0;
            }
            if ((type == DateTimeIntervalType.Auto) || (type == DateTimeIntervalType.Number))
            {
                return start;
            }
            DateTime time = DateTime.FromOADate(start);
            if ((((intervalSize > 0.0) && (intervalSize != 1.0)) && ((type == DateTimeIntervalType.Months) && (intervalSize <= 12.0))) && (intervalSize > 1.0))
            {
                DateTime time2 = time;
                for (DateTime time3 = new DateTime(time.Year, 1, 1, 0, 0, 0); time3 < time; time3 = time3.AddMonths((int) intervalSize))
                {
                    time2 = time3;
                }
                return time2.ToOADate();
            }
            switch (type)
            {
                case DateTimeIntervalType.Years:
                {
                    int year = (int) (((int) (((double) time.Year) / intervalSize)) * intervalSize);
                    if (year <= 0)
                    {
                        year = 1;
                    }
                    time = new DateTime(year, 1, 1, 0, 0, 0);
                    break;
                }
                case DateTimeIntervalType.Months:
                {
                    int month = (int) (((int) (((double) time.Month) / intervalSize)) * intervalSize);
                    if (month <= 0)
                    {
                        month = 1;
                    }
                    time = new DateTime(time.Year, month, 1, 0, 0, 0);
                    break;
                }
                case DateTimeIntervalType.Weeks:
                    time = time.AddDays((double) -(int)time.DayOfWeek);
                    time = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
                    break;

                case DateTimeIntervalType.Days:
                {
                    int day = (int) (((int) (((double) time.Day) / intervalSize)) * intervalSize);
                    if (day <= 0)
                    {
                        day = 1;
                    }
                    time = new DateTime(time.Year, time.Month, day, 0, 0, 0);
                    break;
                }
                case DateTimeIntervalType.Hours:
                {
                    int hour = (int) (((int) (((double) time.Hour) / intervalSize)) * intervalSize);
                    time = new DateTime(time.Year, time.Month, time.Day, hour, 0, 0);
                    break;
                }
                case DateTimeIntervalType.Minutes:
                {
                    int minute = (int) (((int) (((double) time.Minute) / intervalSize)) * intervalSize);
                    time = new DateTime(time.Year, time.Month, time.Day, time.Hour, minute, 0);
                    break;
                }
                case DateTimeIntervalType.Seconds:
                {
                    int second = (int) (((int) (((double) time.Second) / intervalSize)) * intervalSize);
                    time = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, second, 0);
                    break;
                }
                case DateTimeIntervalType.Milliseconds:
                {
                    int millisecond = (int) (((int) (((double) time.Millisecond) / intervalSize)) * intervalSize);
                    time = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, millisecond);
                    break;
                }
            }
            return time.ToOADate();
        }

        internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type)
        {
            return GetIntervalSize(current, interval, type, null, 0.0, DateTimeIntervalType.Number, true, true);
        }

        internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type, Series series, double intervalOffset, DateTimeIntervalType intervalOffsetType, bool forceIntIndex)
        {
            return GetIntervalSize(current, interval, type, series, intervalOffset, intervalOffsetType, forceIntIndex, true);
        }

        internal static double GetIntervalSize(double current, double interval, DateTimeIntervalType type, Series series, double intervalOffset, DateTimeIntervalType intervalOffsetType, bool forceIntIndex, bool forceAbsInterval)
        {
            if ((type == DateTimeIntervalType.Number) || (type == DateTimeIntervalType.Auto))
            {
                return interval;
            }
            if ((series == null) || !series.IsXValueIndexed)
            {
                DateTime time3 = DateTime.FromOADate(current);
                TimeSpan span = new TimeSpan(0L);
                if (type == DateTimeIntervalType.Days)
                {
                    span = TimeSpan.FromDays(interval);
                }
                else if (type == DateTimeIntervalType.Hours)
                {
                    span = TimeSpan.FromHours(interval);
                }
                else if (type == DateTimeIntervalType.Milliseconds)
                {
                    span = TimeSpan.FromMilliseconds(interval);
                }
                else if (type == DateTimeIntervalType.Seconds)
                {
                    span = TimeSpan.FromSeconds(interval);
                }
                else if (type == DateTimeIntervalType.Minutes)
                {
                    span = TimeSpan.FromMinutes(interval);
                }
                else if (type == DateTimeIntervalType.Weeks)
                {
                    span = TimeSpan.FromDays(7.0 * interval);
                }
                else if (type == DateTimeIntervalType.Months)
                {
                    bool flag = false;
                    if (time3.Day == DateTime.DaysInMonth(time3.Year, time3.Month))
                    {
                        flag = true;
                    }
                    time3 = time3.AddMonths((int) Math.Floor(interval));
                    span = TimeSpan.FromDays(30.0 * (interval - Math.Floor(interval)));
                    if (flag && (span.Ticks == 0L))
                    {
                        int num6 = DateTime.DaysInMonth(time3.Year, time3.Month);
                        time3 = time3.AddDays((double) (num6 - time3.Day));
                    }
                }
                else if (type == DateTimeIntervalType.Years)
                {
                    time3 = time3.AddYears((int) Math.Floor(interval));
                    span = TimeSpan.FromDays(365.0 * (interval - Math.Floor(interval)));
                }
                double num7 = time3.Add(span).ToOADate() - current;
                if (forceAbsInterval)
                {
                    num7 = Math.Abs(num7);
                }
                return num7;
            }
            int num = (int) Math.Ceiling((double) (current - 1.0));
            if (num < 0)
            {
                num = 0;
            }
            if ((num >= series.Points.Count) || (series.Points.Count <= 1))
            {
                return interval;
            }
            double num2 = 0.0;
            double num3 = AlignIntervalStart(series.Points[num].XValue, 1.0, type, null);
            double num4 = num3 + GetIntervalSize(num3, interval, type);
            num4 += GetIntervalSize(num4, intervalOffset, intervalOffsetType);
            num3 += GetIntervalSize(num3, intervalOffset, intervalOffsetType);
            if (intervalOffset < 0.0)
            {
                num3 += GetIntervalSize(num3, interval, type);
                num4 += GetIntervalSize(num4, interval, type);
            }
            if ((num == 0) && (current < 0.0))
            {
                DateTime time = DateTime.FromOADate(series.Points[num].XValue);
                DateTime time2 = time;
                switch (type)
                {
                    case DateTimeIntervalType.Years:
                        time2 = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
                        break;

                    case DateTimeIntervalType.Months:
                        time2 = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
                        break;

                    case DateTimeIntervalType.Weeks:
                        time2 = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
                        break;

                    case DateTimeIntervalType.Days:
                        time2 = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
                        break;

                    case DateTimeIntervalType.Hours:
                        time2 = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, 0);
                        break;

                    case DateTimeIntervalType.Minutes:
                        time2 = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second);
                        break;

                    case DateTimeIntervalType.Seconds:
                        time2 = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, 0);
                        break;
                }
                if ((time2.ToOADate() == num3) || (time2.ToOADate() == num4))
                {
                    return (-current + 1.0);
                }
            }
            num++;
            while (num < series.Points.Count)
            {
                if (series.Points[num].XValue >= num4)
                {
                    if ((series.Points[num].XValue > num4) && !forceIntIndex)
                    {
                        num2 = -0.5;
                    }
                    break;
                }
                num++;
            }
            if (num == series.Points.Count)
            {
                num += (series.Points.Count / 5) + 1;
            }
            double num5 = ((num + 1) - current) + num2;
            if (num5 == 0.0)
            {
                return interval;
            }
            return num5;
        }

        internal static bool IndexedSeries(Series series)
        {
            return (series.IsXValueIndexed || SeriesXValuesZeros(series));
        }

        internal static bool IndexedSeries(CommonElements common, params string[] series)
        {
            bool flag = true;
            foreach (string str in series)
            {
                if (common.DataManager.Series[str].IsXValueIndexed)
                {
                    return true;
                }
                if (flag && !SeriesXValuesZeros(common, series))
                {
                    flag = false;
                }
            }
            return flag;
        }

        internal static bool SeriesXValuesZeros(Series series)
        {
            if (!series.xValuesZerosChecked)
            {
                series.xValuesZerosChecked = true;
                series.xValuesZeros = true;
                foreach (DataPoint point in series.Points)
                {
                    if (point.XValue != 0.0)
                    {
                        series.xValuesZeros = false;
                        break;
                    }
                }
            }
            return series.xValuesZeros;
        }

        internal static bool SeriesXValuesZeros(CommonElements common, params string[] series)
        {
            foreach (string str in series)
            {
                if (!SeriesXValuesZeros(common.DataManager.Series[str]))
                {
                    return false;
                }
            }
            return true;
        }
    }
}

